package com.uduemc.biso.node.web.api.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.core.extities.node.custom.LoginNode;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.core.utils.RestResult;
import com.uduemc.biso.core.utils.ResultUtil;
import com.uduemc.biso.node.core.common.dto.download.FeignRepertoryImport;
import com.uduemc.biso.node.core.common.feign.CDownloadFeign;
import com.uduemc.biso.node.core.dto.FeignSaveByListSDownloadAttrAndFindByHostSiteSystemId;
import com.uduemc.biso.node.core.dto.FeignSystemTotal;
import com.uduemc.biso.node.core.entities.HRepertory;
import com.uduemc.biso.node.core.entities.SDownload;
import com.uduemc.biso.node.core.entities.SDownloadAttr;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.core.entities.custom.CategoryQuote;
import com.uduemc.biso.node.core.entities.custom.Download;
import com.uduemc.biso.node.core.feign.SDownloadAttrContentFeign;
import com.uduemc.biso.node.core.feign.SDownloadAttrFeign;
import com.uduemc.biso.node.core.feign.SDownloadFeign;
import com.uduemc.biso.node.core.node.dto.FeignDownloadTableData;
import com.uduemc.biso.node.core.node.extities.DownloadTableData;
import com.uduemc.biso.node.core.node.feign.NDownloadFeign;
import com.uduemc.biso.node.core.utils.RestResultUtil;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.dto.RequestDownload;
import com.uduemc.biso.node.web.api.dto.RequestDownloadAttr;
import com.uduemc.biso.node.web.api.dto.RequestDownloadTableDataList;
import com.uduemc.biso.node.web.api.dto.download.RepertoryImport;
import com.uduemc.biso.node.web.api.service.DownloadService;
import com.uduemc.biso.node.web.api.service.LoginService;
import com.uduemc.biso.node.web.api.service.RepertoryService;
import com.uduemc.biso.node.web.api.service.SystemService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class DownloadServiceImpl implements DownloadService {

    @Resource
    private SystemService systemServiceImpl;

    @Resource
    private RepertoryService repertoryServiceImpl;

    @Resource
    private SDownloadAttrContentFeign sDownloadAttrContentFeign;

    @Resource
    private SDownloadAttrFeign sDownloadAttrFeign;

    @Resource
    private SDownloadFeign sDownloadFeign;

    @Resource
    private NDownloadFeign nDownloadFeign;

    @Resource
    private RequestHolder requestHolder;

    @Resource
    private CDownloadFeign cDownloadFeign;

    @Resource
    private LoginService loginServiceImpl;

    @Override
    public List<SDownloadAttr> getCurrentAttrInfos(long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadAttrFeign.findByHostSiteSystemId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), systemId);
        @SuppressWarnings("unchecked")
        List<SDownloadAttr> data = (List<SDownloadAttr>) RestResultUtil.data(restResult, new TypeReference<List<SDownloadAttr>>() {
        });
        return data;
    }

    @Override
    public SDownloadAttr getCurrentAttrInfosById(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadAttrFeign.findByHostSiteIdAndId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), id);
        SDownloadAttr data = RestResultUtil.data(restResult, SDownloadAttr.class);
        return data;
    }

    @Override
    public boolean existCurrentAttrInfosByIds(List<Long> ids) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadAttrFeign.existByHostSiteIdAndIdList(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), ids);
        Boolean data = RestResultUtil.data(restResult, Boolean.class);
        if (data == null) {
            return false;
        }
        return data;
    }

    @Override
    public boolean existCurrentAttrContentInfosByIds(List<Long> ids) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadAttrContentFeign.existByHostSiteIdAndIdList(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(),
                ids);
        Boolean data = RestResultUtil.data(restResult, Boolean.class);
        if (data == null) {
            return false;
        }
        return data;
    }

    @Override
    public boolean update(SDownloadAttr sDownloadAttr) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadAttrFeign.updateById(sDownloadAttr);
        SDownloadAttr data = RestResultUtil.data(restResult, SDownloadAttr.class);
        return data.getId() != null && data.getId().longValue() == sDownloadAttr.getId().longValue();
    }

    @Override
    public List<SDownloadAttr> updatesAndGetBySystemData(List<SDownloadAttr> listSDownloadAttr, long systemId)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        FeignSaveByListSDownloadAttrAndFindByHostSiteSystemId param = new FeignSaveByListSDownloadAttrAndFindByHostSiteSystemId();
        param.setListSDownloadattr(listSDownloadAttr).setHostId(requestHolder.getHost().getId()).setSiteId(requestHolder.getCurrentSite().getId())
                .setSystemId(systemId);

        RestResult restResult = sDownloadAttrFeign.saveByListSDownloadAttrAndFindByHostSiteSystemId(param);
        @SuppressWarnings("unchecked")
        List<SDownloadAttr> data = (List<SDownloadAttr>) RestResultUtil.data(restResult, new TypeReference<List<SDownloadAttr>>() {
        });
        return data;
    }

    @Override
    public SDownloadAttr attrSave(RequestDownloadAttr requestDownloadAttr)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        SDownloadAttr sDownloadAttr = requestDownloadAttr.getSDownloadAttr(requestHolder);

        long afterId = requestDownloadAttr.getAfterBy();

        Long hostId = requestHolder.getHost().getId();
        Long siteId = requestHolder.getCurrentSite().getId();
        RestResult restResult = sDownloadAttrFeign.findGreaterThanOrEqualToByAfterId(hostId, siteId, afterId);
        @SuppressWarnings("unchecked")
        List<SDownloadAttr> data = (List<SDownloadAttr>) RestResultUtil.data(restResult, new TypeReference<List<SDownloadAttr>>() {
        });
        if (CollectionUtils.isEmpty(data)) {
            return null;
        }
        SDownloadAttr firstSDownloadAttr = data.get(0);
        Integer orderNum = firstSDownloadAttr.getOrderNum();
        int orderNumTime = orderNum.intValue() + 1;
        sDownloadAttr.setOrderNum(new Integer(orderNumTime));

        // 确定 type 类型
        if (sDownloadAttr.getId() == null || sDownloadAttr.getId().longValue() < 1) {
            sDownloadAttr.setType((short) 0);
        } else {
            restResult = sDownloadAttrFeign.findByHostSiteIdAndId(hostId, siteId, sDownloadAttr.getId());
            SDownloadAttr findData = RestResultUtil.data(restResult, SDownloadAttr.class);
            sDownloadAttr.setType(findData.getType());
        }

        // 需要修改的 list
        List<SDownloadAttr> saveList = new ArrayList<>();
        saveList.add(sDownloadAttr);

        if (data.size() > 1) {
            SDownloadAttr oldSDownloadAttr = null;
            for (int i = 1; i < data.size(); i++) {
                if (sDownloadAttr.getId() != null && data.get(i).getId().longValue() == sDownloadAttr.getId().longValue()) {
                    continue;
                }
                orderNumTime = orderNumTime + 1;
                oldSDownloadAttr = data.get(i);
                oldSDownloadAttr.setOrderNum(new Integer(orderNumTime));
                saveList.add(oldSDownloadAttr);
            }
        }

        restResult = sDownloadAttrFeign.saves(saveList);
        Boolean bool = RestResultUtil.data(restResult, Boolean.class);
        if (bool != null && bool.booleanValue() == true) {
            return sDownloadAttr;
        }
        return null;
    }

    @Override
    public boolean deleteAttr(SDownloadAttr sDownloadAttr) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadAttrFeign.deleteByHostSiteAttrId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(),
                sDownloadAttr.getId());
        Boolean bool = RestResultUtil.data(restResult, Boolean.class);
        if (bool == null) {
            return false;
        }
        return bool.booleanValue();
    }

    @Override
    public PageInfo<DownloadTableData> getNodeTableDataList(RequestDownloadTableDataList requestDownloadTableDataList)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        FeignDownloadTableData feignDownloadTableData = requestDownloadTableDataList.getFeignDownloadTableData(requestHolder);

        RestResult restResult = nDownloadFeign.tableDataList(feignDownloadTableData);
        @SuppressWarnings("unchecked")
        PageInfo<DownloadTableData> data = (PageInfo<DownloadTableData>) RestResultUtil.data(restResult, new TypeReference<PageInfo<DownloadTableData>>() {
        });
        return data;
    }

    @Override
    public SDownload getCurrentSDownloadInfo(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadFeign.findByHostSiteIdAndId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), id);
        SDownload data = RestResultUtil.data(restResult, SDownload.class);
        return data;
    }

    @Override
    public boolean updateSDownload(SDownload sDownload) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadFeign.updateById(sDownload);
        SDownload data = RestResultUtil.data(restResult, SDownload.class);
        if (data == null || data.getId() == null || data.getId().longValue() != sDownload.getId().longValue()) {
            return false;
        }
        return true;
    }

    @Override
    public Download saveInfo(RequestDownload requestDownload) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = null;
        Download download = requestDownload.getDownload(requestHolder);
        Download data;
        if (requestDownload.getBase().getId() < 1) {
            // 插入数据
            download.getSDownload().setIsRefuse((short) 0);
            restResult = cDownloadFeign.insert(download);
            data = RestResultUtil.data(restResult, Download.class);
            if (data != null && data.getSDownload() != null) {
                CategoryQuote categoryQuote = data.getCategoryQuote();
                List<Long> categoryIds = new ArrayList<>();
                if (categoryQuote == null) {
                    categoryIds = null;
                } else {
                    categoryIds.add(categoryQuote.getSCategories().getId());
                }
                LoginNode loginNode = requestHolder.getCurrentLoginNode();
                loginNode.saveSystemCategory(data.getSDownload().getSystemId(), categoryIds);
                loginServiceImpl.recacheLoginNode(loginNode);
            }
        } else {
            // 修改数据
            restResult = cDownloadFeign.update(download);
            data = RestResultUtil.data(restResult, Download.class);
        }

        return data;
    }

    @Override
    public Download getCurrentDownloadBySystemDownloadId(long systemId, long downloadId)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Download data = getCurrentDownloadByDownloadId(downloadId);
        if (data.getSDownload().getSystemId().longValue() != systemId) {
            return null;
        }
        return data;
    }

    @Override
    public Download getCurrentDownloadByDownloadId(long downloadId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cDownloadFeign.findByHostSiteDownloadId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), downloadId);
        Download data = RestResultUtil.data(restResult, Download.class);
        return data;
    }

    @Override
    public Download getDownloadBySDownload(SDownload sDownload) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cDownloadFeign.findByHostSiteDownloadId(sDownload.getHostId(), sDownload.getSiteId(), sDownload.getId());
        Download data = RestResultUtil.data(restResult, Download.class);
        return data;
    }

    @Override
    public boolean infoDeletes(List<SDownload> listSDownload) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cDownloadFeign.deleteByListSDownload(listSDownload);
        Boolean data = RestResultUtil.data(restResult, Boolean.class);
        return data;
    }

    @Override
    public int totalByHostId() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getCurrentSite().getId();
        return totalByHostId(hostId);
    }

    @Override
    public int totalByHostId(long hostId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sDownloadFeign.totalByHostId(hostId);
        Integer data = ResultUtil.data(restResult, Integer.class);
        if (data == null) {
            return 0;
        }
        return data.intValue();
    }

    @Override
    public int totalByHostSystemId(long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getCurrentSite().getId();
        return totalByHostSystemId(hostId, systemId);
    }

    @Override
    public int totalByHostSystemId(long hostId, long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        FeignSystemTotal feignSystemTotal = new FeignSystemTotal();
        feignSystemTotal.setHostId(hostId).setSystemId(systemId);
        RestResult restResult = sDownloadFeign.totalByFeignSystemTotal(feignSystemTotal);
        Integer data = ResultUtil.data(restResult, Integer.class);
        if (data == null) {
            return 0;
        }
        return data.intValue();
    }

//	@Override
//	public List<SDownload> findInfosByHostSiteSystemAndIds(FeignSystemDataInfos feignSystemDataInfos)
//			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		RestResult restResult = sDownloadFeign.findInfosByHostSiteSystemAndIds(feignSystemDataInfos);
//		@SuppressWarnings("unchecked")
//		List<SDownload> listSDownload = (ArrayList<SDownload>) RestResultUtil.data(restResult, new TypeReference<ArrayList<SDownload>>() {
//		});
//		return listSDownload;
//	}

    @Override
    public boolean reductionRecycle(List<SDownload> listSDownload) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cDownloadFeign.reductionByListSDownload(listSDownload);
        Boolean data = RestResultUtil.data(restResult, Boolean.class);
        return data;
    }

    @Override
    public boolean cleanRecycle(List<SDownload> listSDownload) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cDownloadFeign.cleanRecycle(listSDownload);
        return RestResultUtil.data(restResult, Boolean.class);
    }

    @Override
    public boolean cleanRecycleAll(SSystem sSystem) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cDownloadFeign.cleanRecycleAll(sSystem);
        return RestResultUtil.data(restResult, Boolean.class);
    }

    @Override
    public JsonResult repertoryImport(RepertoryImport repertoryImport) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getHost().getId();
        Long siteId = requestHolder.getCurrentSite().getId();

        long systemId = repertoryImport.getSystemId();
        List<Long> repertoryIds = repertoryImport.getRepertoryIds();

        SSystem sSystem = systemServiceImpl.getInfoById(systemId, hostId, siteId);
        if (sSystem == null) {
            return JsonResult.illegal();
        }
        if (CollUtil.isEmpty(repertoryIds)) {
            return JsonResult.illegal();
        }
        List<Long> rIds = new ArrayList<>(repertoryIds.size());
        for (Long repertoryId : repertoryIds) {
            if (repertoryId != null && repertoryId.longValue() > 0) {
                rIds.add(repertoryId);
            }
        }
        if (CollUtil.isEmpty(rIds)) {
            return JsonResult.illegal();
        }
        repertoryIds = CollUtil.distinct(rIds);
        if (CollUtil.isEmpty(repertoryIds)) {
            return JsonResult.illegal();
        }

        List<Short> types = new ArrayList<>();
        types.add((short) 1);
        List<HRepertory> listHRepertory = repertoryServiceImpl.findInfosByHostIdTypesIds(hostId, types, repertoryIds);
        if (CollUtil.isEmpty(listHRepertory) || listHRepertory.size() != repertoryIds.size()) {
            return JsonResult.illegal();
        }

        FeignRepertoryImport params = new FeignRepertoryImport();
        params.setSSystem(sSystem).setListHRepertory(listHRepertory);

        RestResult restResult = cDownloadFeign.repertoryImport(params);
        Integer count = RestResultUtil.data(restResult, Integer.class);
        if (count == null || count.intValue() < 1) {
            return JsonResult.assistance();
        }
        return JsonResult.messageSuccess("导入成功，共导入" + count + "条数据！", count);
    }

}
